package corp.edu.amadeus.core.dao.impl;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Collection;
import java.util.List;
import corp.edu.amadeus.core.business.object.ifc.IPersistable;
import corp.edu.amadeus.core.dao.ifc.IDAOSupport;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import corp.edu.amadeus.core.dao.impl.callback.FindByCriteriaCallback;
import corp.edu.amadeus.core.dao.impl.callback.FindByNamedQueryCallback;
import corp.edu.amadeus.core.dao.impl.callback.FindUniqueByNamedQueryCallback;
import corp.edu.amadeus.core.dao.impl.callback.GenericFindCallback;
import corp.edu.amadeus.core.dao.impl.callback.GenericFindCallbackWithOrder;
import org.springframework.orm.hibernate3.HibernateCallback;


public class H3DAOSupportImpl extends HibernateDaoSupport
	implements IDAOSupport {

	public H3DAOSupportImpl() {
        super();
    }


    public Connection connection() {
        return this.getHibernateTemplate().getSessionFactory()
                .getCurrentSession().connection();
    }

    /**
     * @see org.springframework.orm.hibernate3.HibernateAccessor
     * @see com.javaloom.hibernate.ifc.dao.support.IDAOSupport#setFlushMode(int)
     */
    public void setFlushMode(int mode) {
        this.getHibernateTemplate().setFlushMode(mode);
    }


    /**
     * @see org.springframework.orm.hibernate3.HibernateAccessor
     * @see com.javaloom.hibernate.ifc.dao.support.IDAOSupport#setFlushMode(int)
     */
    public void flush() {
        this.getHibernateTemplate().flush();
    }

    public void persist(IPersistable po) {
        this.getHibernateTemplate().save(po);
    }

    public void delete(IPersistable po) {
        this.getHibernateTemplate().delete(po);
    }

    public void update(IPersistable po) {
        this.getHibernateTemplate().update(po);
    }

    public void refresh(IPersistable po) {
        this.getHibernateTemplate().refresh(po);
    }

    public void saveOrUpdate(IPersistable po) {
        this.getHibernateTemplate().saveOrUpdate(po);
    }

    /**
     * Find object by primary key.
     *
     * @param pk the pk of the object to find.
     */
    public Object findByPK(Class clazz, Serializable pk) {
        return this.getHibernateTemplate().load(clazz, pk);
    }

    public List genericFind(Class po, Method[] methods, Object[] reqResults) {
        HibernateCallback hc = new GenericFindCallback(po, methods, reqResults);
        List result = this.getHibernateTemplate().executeFind(hc);
        return result;
    }

    public List genericFind(Class po, Method[] methods, Object[] reqResults,
		   String orderProperty, String orderType) {
	        HibernateCallback hc = new GenericFindCallbackWithOrder(po, methods, reqResults,
	        	orderProperty, orderType);
	        List result = this.getHibernateTemplate().executeFind(hc);
	        return result;
	     }

    public List genericFind(Class po, Method[] methods, Object[] reqResults,
		   String orderProperty, String orderType, int limit) {
	        HibernateCallback hc = new GenericFindCallbackWithOrder(po, methods, reqResults,
	        	orderProperty, orderType, limit);
	        List result = this.getHibernateTemplate().executeFind(hc);
	        return result;
	     }

    public List findByCriteria(final Class target, final Collection criterion,
	    final Collection projections, String orderProperty, String orderType, int limit) {
        HibernateCallback hc = new FindByCriteriaCallback(target, criterion,
        	projections, orderProperty, orderType, limit);
        List result = this.getHibernateTemplate().executeFind(hc);
        return result;
    }

    public List findByCriteria(final Class target, final Collection criterion,
	    final Collection projections, int limit) {
        HibernateCallback hc = new FindByCriteriaCallback(target, criterion, projections, limit);
        List result = this.getHibernateTemplate().executeFind(hc);
        return result;
    }

    public List paginatedFindByCriteria(final Class target,
            final Collection criterion, final int first, final int last) {

        HibernateCallback hc = new FindByNamedQueryCallback(target, criterion,
                first, last);
        List result = this.getHibernateTemplate().executeFind(hc);
        return result;
    }

    public List findByNamedQuery(final String queryName, final Collection params) {

        HibernateCallback hc = new FindByNamedQueryCallback(queryName, params);
        List result = this.getHibernateTemplate().executeFind(hc);
        return result;
    }

    public Object findUniqueByNamedQuery(final String query,
            final Collection params) {

        HibernateCallback hc = new FindUniqueByNamedQueryCallback(query, params);
        List result = this.getHibernateTemplate().executeFind(hc);
        return result.get(0);
    }

    public List findByQuery(final String query) {
    	return this.getHibernateTemplate().find(query);

    }

    public List findByNamedQuery(final String query) {
        HibernateCallback hc = new FindByNamedQueryCallback(query);
        List result = this.getHibernateTemplate().executeFind(hc);
        return result;
    }


}
